﻿Option Strict On
Option Explicit On
Option Infer On

#Region "Imports"
Imports System
Imports System.AddIn
Imports System.Collections.Generic
Imports System.IO
Imports System.Linq
Imports System.Text
Imports System.Windows.Forms
Imports System.Xml.Linq
Imports System.Xml.XPath

Imports GenDotNet.Task.Common
Imports GenDotNet.Generation.Common
Imports <xmlns:s="http://kadgen.com/Select.xsd">
Imports <xmlns:orm="http://kadgen.com/KADORM.xsd">
#End Region

Public Class TestUI
	Private Enum GroupRunStatusEnum
		NotInGroupRun = 0
		InGroupRun
		CancelGroupRun
	End Enum

	Private Delegate Sub EmptyDelegate()
	Private Delegate Function StreamDelegate() As IO.Stream

	' Private Const addInRoot As String = "..\..\..\..\LinqGeneratorAddIns"
	'Private Const testOutputDirectory As String = "..\..\..\temp"
	'Private mMetadataDirectory As String = "..\..\..\..\Metadata"
	Private mGenInputMetadataFileName As String = "GenInputMetadata.xml"
	Private mSPInputMetadataFileName As String = "SPInputMetadata.xml"
	Private mDBInputMetadataFileName As String = "DBMetadata.xml"
	Private mOrmFileName As String = "OrmFile.xml"
	Private mXDoc As XDocument
	Private mMetadataFileName As String
	Private mGenerator As IGenerator
	Private mInRun As Boolean
	Private mGroupRunStatus As GroupRunStatusEnum
	'Private mGenInputMetadataFileName As String = "C:\Users\Kathleen\Current Projects\Universal\Generation\Metadata\Security\GenInputMetadata.xml"

	Private Const CONNECTION_STRING_MASTER As String = _
	 "integrated security=SSPI; data source={0}; persist security info=False; initial catalog=master"
	Private Const CONNECTION_STRING_DATABASE As String = _
	 "integrated security=SSPI; data source={0}; persist security info=False; initial catalog={1}"

#Region "Events and event handlers"
	Private Sub TestUI_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
		' TODO: This should load async
		FillServerCombo()
		If Me.serverComboBox.Items.Count > 0 Then
			Me.serverComboBox.SelectedIndex = 0
		Else
			Me.serverComboBox.Text = My.Settings.DefaultServerName
		End If
		Me.metadataRootComboBox.DataSource = My.Settings.MetadataRoot
		Me.outputSqlDirectoryComboBox.DataSource = My.Settings.OutputSqlDirectory
		Me.outputCodeDirectoryComboBox.DataSource = My.Settings.OutputCodeDirectory
		Me.VBTemplateComboBox.DataSource = My.Settings.TemplatePathVB
		Me.CSharpTemplateComboBox.DataSource = My.Settings.TemplatePathCSharp
		Me.SqlTemplateComboBox.DataSource = My.Settings.TemplatePathSql
		Me.VBTemplateComboBox.SelectedIndex = 0
		Me.CSharpTemplateComboBox.SelectedIndex = 0
		Me.SqlTemplateComboBox.SelectedIndex = 0
		FillDatabaseCombo()
	End Sub

	Private Sub serverTextBox_Leave(ByVal sender As System.Object, ByVal e As System.EventArgs)
		FillDatabaseCombo()
	End Sub

	Private Sub extractMetadataButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ExtractMetadataButton.Click
		ExtractMetadata(serverComboBox.Text, DatabaseName, False)
	End Sub

	Private Sub extractObjectMetadataButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles extractObjectMetadataButton.Click
		ExtractMetadata(serverComboBox.Text, DatabaseName, True)
	End Sub

	Private Sub morphSPButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles morphSPButton.Click
		MorphMetadataForSP()
	End Sub

	Private Sub morphObjectButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles morphObjectButton.Click
		MorphMetadataForObjects()
	End Sub

	Private Sub generateSelectButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles generateSelectButton.Click
		GenerateSqlAndLoad("SelectSpTemplate", "Select", GeneratorCategory.RetrieveStoredProc)
	End Sub

	Private Sub generateSelectChildren_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles generateSelectChildren.Click
		GenerateSqlAndLoad("SelectChildrenSpTemplate", "SelectChildren", GeneratorCategory.RetrieveStoredProc)
	End Sub

	Private Sub generateSelectHierarchy_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles generateSelectHierarchy.Click
		GenerateSqlAndLoad("SelectHierarchySpTemplate", "SelectHierarchy", GeneratorCategory.RetrieveStoredProc)
	End Sub

	Private Sub generateCreateButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles generateCreateButton.Click
		GenerateSqlAndLoad("CreateSpTemplate", "Create", GeneratorCategory.CreateStoredProc)
	End Sub

	Private Sub generateUpdateButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles generateUpdateButton.Click
		GenerateSqlAndLoad("UpdateSpTemplate", "Update", GeneratorCategory.UpdateStoredProc)
	End Sub

	Private Sub generateDeleteButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles generateDeleteButton.Click
		GenerateSqlAndLoad("DeleteSpTemplate", "Delete", GeneratorCategory.DeleteStoredProc)
	End Sub

	Private Sub generateSetSelectButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles generateSetSelectButton.Click
		GenerateSqlAndLoad("SetSelectSpTemplate", "SetSelect", GeneratorCategory.RetrieveSetStoredProc)
	End Sub

	Private Sub genBizObjectButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles genBizObjectButton.Click
		GenerateDotNetSet(VBTemplateAssemblyName, "BizObject", "RootObject")
	End Sub

	Private Sub genRoListButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles genRoListButton.Click
		GenerateDotNetSet(VBTemplateAssemblyName, "ReadOnlyList")
	End Sub

	Private Sub genRoItemButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles genRoItemButton.Click
		GenerateDotNetSet(VBTemplateAssemblyName, "ReadOnlyItem")
	End Sub

	Private Sub genChildCollectionButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles genChildCollectionButton.Click
		GenerateDotNetSet(VBTemplateAssemblyName, "ChildCollection")
	End Sub

	Private Sub genBaseDalButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles genBaseDalButton.Click
      GenerateDotNetSet(VBTemplateAssemblyName, "Dal", "BaseDAL")
	End Sub

	Private Sub genSqlDalButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles genSqlDalButton.Click
		GenerateDotNetSet(VBTemplateAssemblyName, "SqlDAL")
	End Sub

	Private Sub genSwitchableCSharpButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles genSwitchableCSharpButton.Click
		GenerateDotNet(CSharpTemplateName, "genRootObjectTemplate", "genSwitchable")
	End Sub

	Private Sub switchableDesignerCSharpButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles switchableDesignerCSharpButton.Click
		GenerateDotNet(CSharpTemplateName, "RootObjectTemplateDesigner", "SwitchableDesigner")
	End Sub

	Private Sub switchableCSharpButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles switchableCSharpButton.Click
		GenerateDotNet(CSharpTemplateName, "RootObjectTemplate", "Switchable")
	End Sub

	Private Sub generateCslaSingleButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
		GenerateDotNet(VBTemplateAssemblyName, "DNRTemplate", "DNR Tempate")
	End Sub

	Private Sub generateCslaButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
		GenerateDotNet(VBTemplateAssemblyName, "DNRFormalTemplate", "DNR Formal Template")
	End Sub

	Private Sub runAllButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles runAllButton.Click
      RunGroup(29, makeSPMetadataButton, runAllStoredProcButton, makeObjectMetadataButton, runAllVBButton)
	End Sub

	Private Sub makeSPMetadataButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles makeSPMetadataButton.Click
		RunGroup(2, ExtractMetadataButton, morphSPButton)
	End Sub

	Private Sub makeObjectMetadataButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles makeObjectMetadataButton.Click
		RunGroup(2, ExtractMetadataButton, morphObjectButton)
	End Sub

	Private Sub runAllStoredProcButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles runAllStoredProcButton.Click
      RunGroup(7, generateSelectButton, generateSelectChildren, generateCreateButton, generateUpdateButton, generateDeleteButton, generateSetSelectButton)
	End Sub

	Private Sub runAllVBButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles runAllVBButton.Click
      RunGroup(17, genBizObjectButton, genRoListButton, genRoItemButton, genChildCollectionButton, genBaseDalButton)
	End Sub

	Private Sub CancelToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CancelToolStripMenuItem.Click
		CancelGroupRun()
	End Sub

	''' <summary>
	''' Forces database list to update when the server is changed
	''' </summary>
	''' <param name="sender"></param>
	''' <param name="e"></param>
	''' <remarks>GGC 21 March 2008</remarks>
	Private Sub serverComboBox_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles serverComboBox.SelectedIndexChanged
		FillDatabaseCombo()
	End Sub
#End Region

#Region "Private properties"

	Private ReadOnly Property GenInputMetadata() As String
		Get
			Return IO.Path.Combine(MetadataDirectory, mGenInputMetadataFileName)
		End Get
	End Property

	Private ReadOnly Property SPInputMetadata() As String
		Get
			Return IO.Path.Combine(MetadataDirectory, mSPInputMetadataFileName)
		End Get
	End Property

	Private ReadOnly Property DBInputMetadata() As String
		Get
			Return IO.Path.Combine(MetadataDirectory, mDBInputMetadataFileName)
		End Get
	End Property

	Private ReadOnly Property MetadataDirectory() As String
		Get
			Dim dir = IO.Path.Combine(metadataRootComboBox.Text, DatabaseName)
			If Not IO.Directory.Exists(dir) Then
				IO.Directory.CreateDirectory(dir)
			End If
			Return dir
		End Get
	End Property

	Private ReadOnly Property DatabaseName() As String
		Get
			Return Me.databaseComboBox.Text
		End Get
	End Property

	Private ReadOnly Property OrmFile() As String
		Get
			Return IO.Path.Combine(MetadataDirectory, mOrmFileName)
		End Get
	End Property

	Private ReadOnly Property VBTemplateAssemblyName() As String
		Get
			Return VBTemplateComboBox.Text
		End Get
	End Property

	Private ReadOnly Property SqlTemplateAssemblyName() As String
		Get
			Return SqlTemplateComboBox.Text
		End Get
	End Property

	Private ReadOnly Property CSharpTemplateName() As String
		Get
			Return CSharpTemplateComboBox.Text
		End Get
	End Property

	Private ReadOnly Property OutputSqlDirectory() As String
		Get
			Return Me.outputSqlDirectoryComboBox.Text
		End Get
	End Property

	Private ReadOnly Property OutputCodeDirectory() As String
		Get
			Return Me.outputCodeDirectoryComboBox.Text
		End Get
	End Property

	Private ReadOnly Property InRun() As Boolean
		Get
			Return mInRun
		End Get
	End Property

	Public Sub startRun(ByVal item As String, ByVal startPercent As Int32)
		mInRun = True
		Me.Cursor = Windows.Forms.Cursors.WaitCursor
		Me.statusLabel.Text = "Running {0}: ".FormatString(item)
		Me.progressBar.Maximum = 100
		Me.progressBar.Value = startPercent
		Me.Refresh()
		Console.WriteLine("Start Run {0}: {1}".FormatString(item, DateTime.Now.Ticks \ 1000).ToString)
		' Assume it will be set once per item running
		Me.overallProgressBar.Value += 1
	End Sub

	Public Sub stopRun(ByVal failed As Boolean)
		mInRun = False
		Me.Cursor = Windows.Forms.Cursors.Default
		If failed Then
			Me.statusLabel.Text = "Failed"
		Else
			Me.statusLabel.Text = "Done"
		End If
		Console.WriteLine("Stop Run: {0}".FormatString(DateTime.Now.Ticks \ 1000).ToString)
		Me.progressBar.Value = 100
	End Sub

	Private ReadOnly Property GroupRunStatus() As GroupRunStatusEnum
		Get
			Return mGroupRunStatus
		End Get
	End Property

	Private Sub StartGroupRun(ByVal count As Int32)
		Me.overallProgressBar.Visible = True
		' Three is empirical. I think I'm missing a count somewhere
		Me.overallProgressBar.Maximum = count + 3
		Me.overallProgressBar.Value = 0
		Me.cancelRunButton.Visible = True
		mGroupRunStatus = GroupRunStatusEnum.InGroupRun
	End Sub

	Private Sub CompleteGroupRun()
		Me.overallProgressBar.Visible = False
		mGroupRunStatus = GroupRunStatusEnum.NotInGroupRun
		Me.cancelRunButton.Visible = False
	End Sub

	Private Sub CancelGroupRun()
		Me.overallProgressBar.BackColor = Drawing.Color.Red
		Me.overallProgressBar.ForeColor = Drawing.Color.Yellow
		mGroupRunStatus = GroupRunStatusEnum.CancelGroupRun
	End Sub

#End Region

#Region "Private Methods"
	Private Sub ExtractMetadata( _
		 ByVal serverName As String, _
		 ByVal databaseName As String, _
		 ByVal runStoredProcs As Boolean)
		Dim failed = False
		Try
			startRun("ExtractMetadataButton", 25)
			Dim metadataStream = KadGen.LogicWrappers2008.ExtractMetadata.Extract(serverName, databaseName)
			metadataStream.Position = 0
			Dim reader = Xml.XmlReader.Create(metadataStream)
			Dim xDoc = XDocument.Load(reader)
			xDoc.Save(DBInputMetadata)
		Catch ex As Exception
			DisplayError(ex)
			failed = True
		Finally
			stopRun(failed)
		End Try
	End Sub

	Private Sub MorphMetadataForSP()
		MorphMetadata(SPInputMetadata, Function() KadGen.LogicWrappers2008.MorphMetadata.MorphForSP(DBInputMetadata, OrmFile))
	End Sub

	Private Sub MorphMetadataForObjects()
		MorphMetadata(GenInputMetadata, Function() KadGen.LogicWrappers2008.MorphMetadata.MorphForObjects(DBInputMetadata, OrmFile))
	End Sub

	Private Sub MorphMetadata( _
		 ByVal outputFileName As String, _
		 ByVal del As StreamDelegate)
		Dim failed = False
		Try
			startRun("MorphMetadata", 25)
			Dim stream = del()
			stream.Position = 0
			Dim reader = Xml.XmlReader.Create(stream)
			Dim xDoc = XDocument.Load(reader)
			xDoc.Save(outputFileName)
		Catch ex As Exception
			DisplayError(ex)
			failed = True
		Finally
			stopRun(failed)
		End Try
	End Sub

	Private Sub GenerateDotNet( _
		 ByVal assemblyName As String, _
		 ByVal templateName As String, _
		 ByVal subDirectoryName As String)
		Generate(assemblyName, templateName, subDirectoryName, GenInputMetadata, GeneratorCategory.Object)
	End Sub

	Private Sub GenerateDotNetSet( _
		 ByVal assemblyName As String, _
		 ByVal ParamArray templateRootNames() As String)
		For Each templateRootName In templateRootNames
			If mGroupRunStatus = GroupRunStatusEnum.CancelGroupRun Then
				Exit For
			End If
			Dim templateName = "gen" & templateRootName & "Template"
			Dim subdirectoryRootName = templateRootName
			Dim subDirectoryName = Path.Combine(subdirectoryRootName, "Autogenerated")
			Generate(assemblyName, templateName, subDirectoryName, GenInputMetadata, GeneratorCategory.Object)
			templateName = templateRootName & "DesignerTemplate"
			subDirectoryName = Path.Combine(subdirectoryRootName, "Designer")
			Generate(assemblyName, templateName, subDirectoryName, GenInputMetadata, GeneratorCategory.Object)
			templateName = templateRootName & "Template"
			subDirectoryName = Path.Combine(subdirectoryRootName, "Editable")
			Generate(assemblyName, templateName, subDirectoryName, GenInputMetadata, GeneratorCategory.Object)
		Next
	End Sub

	Private Sub GenerateSqlAndLoad( _
		ByVal templateName As String, _
		ByVal subDirectoryName As String, _
		ByVal category As String)
		Generate(SqlTemplateAssemblyName, templateName, subDirectoryName, SPInputMetadata, category, True)
	End Sub

	Private Sub Generate( _
		ByVal assemblyName As String, _
		ByVal templateName As String, _
		ByVal subDirectoryName As String, _
		ByVal metadataName As String, _
		ByVal category As String)
		Generate(assemblyName, templateName, subDirectoryName, metadataName, category, False)
	End Sub

	Private Sub Generate( _
		 ByVal assemblyName As String, _
		 ByVal templateName As String, _
		 ByVal subDirectoryName As String, _
		 ByVal metadataName As String, _
		 ByVal category As String, _
		 ByVal loadStoredProc As Boolean)
		Dim failed = False
		Try
			startRun("Generate {0}".FormatString(templateName), 5)
			Dim connection As Data.SqlClient.SqlConnection = Nothing
			If loadStoredProc Then
				connection = New Data.SqlClient.SqlConnection(String.Format(CONNECTION_STRING_DATABASE, serverComboBox.Text, DatabaseName))
			End If

			Dim addInName = "LinqGeneratorTest"
			'Dim assemblyName = My.Settings.TemplateLocation
			Dim outputDirectory = String.Empty
			If category = GeneratorCategory.Object Then
				outputDirectory = OutputCodeDirectory
			Else
				outputDirectory = OutputSqlDirectory
			End If
			Dim rootDirectory = IO.Path.Combine(IO.Path.Combine(outputDirectory, DatabaseName), subDirectoryName)
			Dim token = 0
			Dim runBase = Generator.SetXmlDocument(category.ToString(), Me.XDoc(metadataName), token)
			If runBase Is Nothing Then
				failed = True
				Exit Sub
			End If
			Dim elements As IEnumerable(Of XElement) = Nothing
			If category = GeneratorCategory.Object Then
				elements = runBase...<s:Object>
			ElseIf category = GeneratorCategory.RetrieveStoredProc Then
				elements = runBase...<s:RetrieveStoredProc>
			ElseIf category = GeneratorCategory.RetrieveSetStoredProc Then
				elements = runBase...<s:RetrieveSetProc>
			ElseIf category = GeneratorCategory.RetrieveChildrenStoredProc Then
				elements = runBase...<s:RetrieveChildrenStoredProc>
			ElseIf category = GeneratorCategory.RetrieveHierarchyStoredProc Then
				elements = runBase...<s:RetrieveHierarchyStoredProc>
			ElseIf category = GeneratorCategory.CreateStoredProc Then
				elements = runBase...<s:CreateStoredProc>
			ElseIf category = GeneratorCategory.DeleteStoredProc Then
				elements = runBase...<s:DeleteStoredProc>
			ElseIf category = GeneratorCategory.UpdateStoredProc Then
				elements = runBase...<s:UpdateStoredProc>
			End If
			Me.progressBar.Value = 10
			Dim count = 0
			For Each item In elements
				Dim fileName As String = String.Empty
				' This access to XML is acceptable because it is hitting the local stream of well known structure - NOT the main metadata
				Dim output = Generator.Generate(item.@Name, token, assemblyName, templateName, fileName)
				' The template may refuse to create something - effectively allowing a filter at the template level
				' If the template is refusing becuase of a problem, it should throw an error or log, the details 
				' of whic are not yet worked out. 
				If output IsNot Nothing Then
					If Not IO.Directory.Exists(rootDirectory) Then
						IO.Directory.CreateDirectory(rootDirectory)
					End If
					Dim fullFilName = IO.Path.Combine(rootDirectory, fileName)
					IO.File.WriteAllText(fullFilName, output)
					' This is a temporary hack. At the very least we should have pre and post delegates for the process and file
					If loadStoredProc And Not mGroupRunStatus = GroupRunStatusEnum.CancelGroupRun Then
						LoadSqlScripts.RunScript(fullFilName, connection)
					End If
				End If
				count += 1
				Me.progressBar.Value = 20 + CInt((count * 80 / elements.Count))
			Next
		Catch ex As Exception
			DisplayError(ex)
			failed = True
		Finally
			stopRun(failed)
		End Try
	End Sub

	Private ReadOnly Property Generator() As IGenerator
		Get
			If mGenerator Is Nothing Then
				mGenerator = New GeneratorLinq()
			End If
			Return mGenerator
		End Get
	End Property

	Private ReadOnly Property XDoc(ByVal metadataFileName As String) As XDocument
		Get
			Try
				If Me.mXDoc Is Nothing OrElse _
					Not metadataFileName.EqualsIgnoreCase(Me.mMetadataFileName) Then
					Dim reader = Xml.XmlReader.Create(metadataFileName)
					Me.mXDoc = XDocument.Load(reader)
					Me.mMetadataFileName = metadataFileName
				End If
				Return mXDoc
			Catch ex As Exception
				Windows.Forms.MessageBox.Show("Metadata file not found for this database. Try Extract/Morp for business objects or select the right database")
			End Try
			Return Nothing
		End Get
	End Property

	Private Sub RunGroup(ByVal count As Int32, ByVal ParamArray buttons() As Windows.Forms.Control)
		' The count can't be determined by the buttons because buttons will sometimes call a set of buttons, iow, RunAll shoudl be 15, not 4
		' Because of the same nesting, the group run may have already been started and the outer wins
		Dim thisMethodStartedGroupRun As Boolean = False
		If mGroupRunStatus = GroupRunStatusEnum.NotInGroupRun Then
			StartGroupRun(count)
			thisMethodStartedGroupRun = True
		End If
		Try
			For Each button As Windows.Forms.Button In buttons
				If mGroupRunStatus = GroupRunStatusEnum.CancelGroupRun Then
					Exit For
				End If
				button.PerformClick()
			Next
		Finally
			' This is hit whether or not user cancels
			If thisMethodStartedGroupRun Then
				CompleteGroupRun()
			End If
		End Try

	End Sub

	Private Sub DisplayError(ByVal ex As Exception)
		' modified to use StringBuilder for better formatting: GGC 21 March 2008
		Dim message As New StringBuilder(256)
		With message
			.AppendLine("Exception:")
			.AppendLine("{0}")
			.AppendLine("{1}")
			.AppendLine("Do you want to continue the group run?")
		End With
		Dim dialogResult = MessageBox.Show(message.ToString.FormatString(ex.Message, Me.statusLabel.Text), _
		"GenDotNet Exception Encountered", MessageBoxButtons.YesNo)
		If dialogResult <> Windows.Forms.DialogResult.Yes Then
			CancelGroupRun()
		End If
	End Sub

	Private Sub FillDatabaseCombo()
		If Not String.IsNullOrEmpty(serverComboBox.Text) Then
			Dim connection = New Data.SqlClient.SqlConnection(String.Format(CONNECTION_STRING_MASTER, serverComboBox.Text))
			Try
				connection.Open()
				Dim ds = connection.GetSchema("Databases")
				Dim q = From row In ds.Rows.OfType(Of Data.DataRow)() _
				 Select Name = row(0).ToString() _
				 Order By Name
				databaseComboBox.Items.Clear()
				' modified to use AddRange: GGC 21 March 2008
				databaseComboBox.Items.AddRange(q.ToArray)
				databaseComboBox.SelectedIndex = 0
			Catch
				connection.Close()
			End Try
		End If
	End Sub

	''' <summary>
	''' Gets the list of SQL server instances visible on the network and populates the combo box
	''' </summary>
	''' <remarks>
	''' localhost added as default option: GGC 21 March 2008
	''' server names sorted: GGC 21 March 2008
	''' </remarks>
	Private Sub FillServerCombo()
		Dim factory = System.Data.Common.DbProviderFactories.GetFactory("System.Data.SqlClient")
		Dim dsE = factory.CreateDataSourceEnumerator
		Dim dtInstances = dsE.GetDataSources

		' sort servers by name, then add localhost into the server list at the default position
		Dim dvSortedServers = New Data.DataView(dtInstances)
		dvSortedServers.Sort = "ServerName"
		Dim servers As New List(Of String)
		For Each server As Data.DataRowView In dvSortedServers
			servers.Add(server("ServerName").ToString)
		Next

		' add localhost at the default position
		servers.Insert(0, "localhost")

		' Bind the combo box
		serverComboBox.DataSource = servers
	End Sub
#End Region
End Class